////////////////////////////////////////////////////////////////////////////////
//
//  FLYING KIWI BV
//  Copyright 2010 Flying Kiwi BV
//  All Rights Reserved.
//
//  NOTICE: Flying Kiwi permits you to use, modify, and distribute this file
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////
package plantool.api {
	//--------------------------------------------------------------------------
	//  Imports
	//--------------------------------------------------------------------------
	import flash.events.Event;
	
	import kiwi.utils.Validation;
	
	import plantool.core.CoreApi;
	import plantool.events.DateEvent;
	import plantool.settings.Setting;
	import plantool.settings.Settings;
	
	//--------------------------------------------------------------------------
	//  [Metadata (Events, Style, Effects etc)]
	//--------------------------------------------------------------------------
	[Event(name="date_changed"	, type="plantool.events.DateEvent")]
	
	//--------------------------------------------------------------------------
	//  Class declaration
	//--------------------------------------------------------------------------
	public class DateApi extends CoreApi {
		//--------------------------------------------------------------------------
		//Class constants
		//--------------------------------------------------------------------------
		
		//--------------------------------------------------------------------------
		//Class variables
		//--------------------------------------------------------------------------
		private static var _instance:DateApi	= null;
		private var _date:Date					= null;
		private var _numDays:uint				= 0;
		
		//--------------------------------------------------------------------------
		//Class properties
		//--------------------------------------------------------------------------
		public function get currentDate():Date {
			return new Date(_date);
		}
		public function get dayStartHour():uint {
			return parseInt(settings.getSetting(Settings.SETTING_START_HOUR).value);
		}
		public function get daysPerWeek():uint {
			return parseInt(settings.getSetting(Settings.SETTING_DAYS_PER_WEEK).value);
		}
		public function get hoursPerDay():uint {
			return parseInt(settings.getSetting(Settings.SETTING_HOURS_PER_DAY).value);
		}
		public function get weekStartsOn():uint {
			return parseInt(settings.getSetting(Settings.SETTING_WEEK_STARTS_ON).value);
		}
		
		
		public function get activeWeek():int {
			return calculateWeekNumber(_date);
		}
		public function set activeWeek(value:int):void {
			if (value != activeWeek) {
				var oldDate:Date = new Date(getStartDate());
				
				var year:Number = _date.getFullYear();
				
				var d:Date = new Date();
				d.setFullYear(year);
				var curWeek:int = calculateWeekNumber(d);
				
				var diff:int 	= value - curWeek;
				_date			= new Date();
				_date.setFullYear(year);
				_date.date		+= (diff * 7);
				
				dispatchEvent(new DateEvent(DateEvent.DATE_CHANGED, oldDate));
			}
		}
		
		public function hasWeek53(year:Number):Boolean {
//				var d:Date = new Date();
//				var curWeek:int = calculateWeekNumber(d);
//				
//				var diff:int 	= 53 - curWeek;
//				_date			= new Date();
//				_date.setFullYear(year);
//				_date.date		+= (diff * 7);
//				
//				if (_date.getFullYear() == _date.getFullYear()) {
//					return true;
//				}
				return false;
		}
		
		//--------------------------------------------------------------------------
		//Constructor and Destructor
		//--------------------------------------------------------------------------
		public function DateApi(pvt:PrivateConstructorClass) {
			super();
		}
		
		//--------------------------------------------------------------------------
		//Class methods
		//--------------------------------------------------------------------------
		public static function getInstance():DateApi {
			//check if instance exists, if not create one
			if (!Validation.isSet(_instance)) {
				_instance = new DateApi(new PrivateConstructorClass());
			}
			
			//return instance
			return _instance;
		}
		
		public function calculateWeekNumber(date:Date):int {
			//
			// 1 - CALC JULIAN DATE NUMBER (note: nothing to do with the Julian calendar)
			//
			var day:Date 		= new Date(date);
			//day.date			+= _dateOffset;			//get days for selected week
			
			var wfullyear:int 	= day.getFullYear();
			var wmonth:int 		= day.getMonth() + 1;
			var wdate:int 		= day.getDate();
			//
			var wa:int = Math.floor((14 - wmonth) / 12);
			var wy:int = wfullyear + 4800 - wa;
			var wm:int = wmonth + 12 * wa - 3;
			//
			// wJDN is the Julian Day Number
			//
			var wJDN:int = wdate + Math.floor(((153 * wm) + 2) / 5) + wy * 365
				+ Math.floor(wy / 4)
				- Math.floor(wy / 100)
				+ Math.floor(wy / 400) - 32045;
			//
			// 2 - CALC WEEK NB
			//
			var d4:int = (((wJDN + 31741 - (wJDN % 7)) % 146097) % 36524) % 1461;
			var L:int = Math.floor(d4 / 1460);
			var d1:int = ((d4 - L) % 365) + L;
			var wweekNb:int = Math.floor(d1 / 7) + 1;
			
			return wweekNb;
		}
		
		private function initSettings():void {
			//get settings
			var weekStartOn:Setting = new Setting();
			weekStartOn.setting_id	= Settings.SETTING_WEEK_STARTS_ON;
			weekStartOn.value		= "1";
			weekStartOn.type		= Settings.TYPE_INT;
			settings.initSetting(weekStartOn);
			
			//get settings
			var hPerDay:Setting = new Setting();
			hPerDay.setting_id	= Settings.SETTING_HOURS_PER_DAY;
			hPerDay.value		= "8";
			hPerDay.type		= Settings.TYPE_INT;
			settings.initSetting(hPerDay);
			
			//get settings
			var startAtHour:Setting = new Setting();
			startAtHour.setting_id	= Settings.SETTING_START_HOUR;
			startAtHour.value		= "8";
			startAtHour.type		= Settings.TYPE_INT;
			settings.initSetting(startAtHour);
			
			//get days per week
			var daysPerWeek:Setting = new Setting();
			daysPerWeek.setting_id	= Settings.SETTING_DAYS_PER_WEEK;
			daysPerWeek.value		= "5";
			daysPerWeek.type		= Settings.TYPE_INT;
			settings.initSetting(daysPerWeek);
			
			//show Saterday
			var showSaterday:Setting = new Setting();
			showSaterday.setting_id	= Settings.SETTING_SHOW_SATERDAY;
			showSaterday.value		= "0";
			showSaterday.type		= Settings.TYPE_INT;
			settings.initSetting(showSaterday);
			
			//show Saterday
			var showSunday:Setting = new Setting();
			showSunday.setting_id	= Settings.SETTING_SHOW_SUNDAY;
			showSunday.value		= "0";
			showSunday.type			= Settings.TYPE_INT;
			settings.initSetting(showSunday);
		}
		
		public function validateDay(day1:Date, day2:Date):Boolean {
			//validate date
			if (day1.getDate() == day2.getDate() &&
				day1.getMonth() == day2.getMonth() && 
				day1.getFullYear() == day2.getFullYear()) {
				return true;
			}
			
			//return false default
			return false;
		}
		
		public function getDaysBetweenDates(date1:Date,date2:Date):int {
			var one_day:Number 			= 1000 * 60 * 60 * 24
			var date1_ms:Number 		= date1.getTime();
			var date2_ms:Number 		= date2.getTime();            
			var difference_ms:Number 	= Math.abs(date1_ms - date2_ms)            
			return Math.round(difference_ms/one_day);
		}
		
		public function getStartDate():Date {
			//create new date
			var date:Date		= new Date(_date);
			var start:Number 	= weekStartsOn - (date.day);
			//set start day
			date.date 			+= start;
			
			//set start day
			date.hours			= dayStartHour;
			date.minutes		= 0;
			date.seconds		= 0;
			date.milliseconds	= 0;
			
			//return date
			return date;
		}
		
		public function getVisibleDates():Vector.<Date> {
			//create startdate and list to return
			var sdate:Date 			= getStartDate();
			var list:Vector.<Date> 	= new Vector.<Date>();
			
			//create a date for each day
			for (var i:uint = 0; i < _numDays; i++) {
				//store date in list
				list.push(new Date(sdate));
				
				//increase date
				sdate.date += 1;
				if (sdate.day == 6 && settings.getSetting(Settings.SETTING_SHOW_SATERDAY).value == "0") {
					sdate.date += 1;
				}
				if (sdate.day == 0 && settings.getSetting(Settings.SETTING_SHOW_SUNDAY).value == "0") {
					sdate.date += 1;
				}
			}
			return list;
		}
		
		public override function install():void {
			//init the current date
			_date = new Date();

			//calculate number of days to show
			_numDays = Math.floor((base.stage.stageWidth - 300) / 162);
			
			//init settings
			initSettings();
			
			//nothing to install, were just ready
			dispatchEvent(new Event(Event.COMPLETE));
		}
	}
}

//--------------------------------------------------------------------------
//END OF PACKAGE
//Define the PrivateConstructorClass here so an instance cannot be by anyone
//except for the class defined in the above package
//--------------------------------------------------------------------------
class PrivateConstructorClass {
	//--------------------------------------------------------------------------
	//Constructor and Destructor
	//--------------------------------------------------------------------------
	public function PrivateConstructorClass() {
	}
}

/*
////////////////////////////////////////////////////////////////////////////////
//
//  FLYING KIWI BV
//  Copyright 2010 Flying Kiwi BV
//  All Rights Reserved.
//
//  NOTICE: Flying Kiwi permits you to use, modify, and distribute this file
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////
package plantool.managers
{
//--------------------------------------------------------------------------
//  Imports
//--------------------------------------------------------------------------
import flash.events.Event;

import kiwi.events.EventDispatcher;

//--------------------------------------------------------------------------
//  [Metadata (Events, Style, Effects etc)]
//--------------------------------------------------------------------------
[Event(name="date_changed"	, type="plantool.managers.KalenderManager")]

//--------------------------------------------------------------------------
//  Class declaration
//--------------------------------------------------------------------------
public class KalenderManager extends EventDispatcher {
//--------------------------------------------------------------------------
//Class constants
//--------------------------------------------------------------------------
public static const DATE_CHANGED:String = "date_changed";

public const _dayNames:Array 	= ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"];
public const _monthNames:Array 	= ["jan", "feb", "maart", "april", "mei", "juni", "juli", "aug", "sept", "okt", "nov", "dec"];

//--------------------------------------------------------------------------
//Class variables
//--------------------------------------------------------------------------
private static var _instance:KalenderManager		= null;

private var _date:Date			= null;

//--------------------------------------------------------------------------
//Class properties
//--------------------------------------------------------------------------

public function get year():Number
{
return _date.getFullYear();
}

public function get yearText():String {
var m:Date = week[0];
var z:Date = new Date(m);
z.date += 6;

if (m.getFullYear() != z.getFullYear()) {
return m.getFullYear().toString().substr(2, 2) + "/" + z.getFullYear().toString().substr(2, 2);
}
return m.getFullYear().toString();
}

public function set year(value:Number):void {
_date.setFullYear(value);

dispatchEvent(new Event(DATE_CHANGED));
}

public function get startDay():Date {
var start:Number 			= 1 - (_date.day);
var day:Date 				= new Date(_date);
day.date					+= start;				//start on monday
day.hours					= 0;
day.minutes					= 0;
day.seconds					= 0;
day.milliseconds			= 1;

return day;
}

public function get week():Vector.<Date> {
var days:Vector.<Date>		= new Vector.<Date>();
var day:Date 				= new Date(_date);
//day.date					+= _dateOffset;			//get days for selected week
var start:Number 			= 1 - (_date.day);
day.date					+= start;				//start on monday
day.hours					= 0;
day.minutes					= 0;
day.seconds					= 0;
day.milliseconds			= 1;

for (var i:int = 0; i < 5; i += 1) {
var d:Date = new Date(day.valueOf());
//var ar:Array = [_dayNames[day.day], day.date, _monthNames[day.month], d];
days.push(d);

day.date += 1;
}

return days;
}

public function get weekNumber():int {
return calculateWeekNumber(_date);
}

public function set weekNumber(value:int):void {
if (value != weekNumber) {
var year:Number = _date.getFullYear();

var d:Date = new Date();
d.setFullYear(year);
var curWeek:int = calculateWeekNumber(d);

var diff:int 	= value - curWeek;
_date			= new Date();
_date.setFullYear(year);
_date.date		+= (diff * 7);

dispatchEvent(new Event(DATE_CHANGED));
}
}

//--------------------------------------------------------------------------
//Constructor and Destructor
//--------------------------------------------------------------------------
public function KalenderManager(pvt:PrivateConstructorClass) {
super();

_date 		= new Date();
}

//--------------------------------------------------------------------------
//Class methods
//--------------------------------------------------------------------------
public static function getInstance():KalenderManager {
if(_instance == null) {
_instance = new KalenderManager(new PrivateConstructorClass());
}

return _instance;
}

public function setYearAndWeek(year:Number, week:uint):void {
if (_date.getFullYear() != year) {
_date.setFullYear(year);
}

if (weekNumber != week) {
weekNumber = week;
} else {
dispatchEvent(new Event(DATE_CHANGED));
}
}

public function calculateWeekNumber(date:Date):int {
//
// 1 - CALC JULIAN DATE NUMBER (note: nothing to do with the Julian calendar)
//
var day:Date 		= new Date(date);
//day.date			+= _dateOffset;			//get days for selected week

var wfullyear:int 	= day.getFullYear();
var wmonth:int 		= day.getMonth() + 1;
var wdate:int 		= day.getDate();
//
var wa:int = Math.floor((14 - wmonth) / 12);
var wy:int = wfullyear + 4800 - wa;
var wm:int = wmonth + 12 * wa - 3;
//
// wJDN is the Julian Day Number
//
var wJDN:int = wdate + Math.floor(((153 * wm) + 2) / 5) + wy * 365
+ Math.floor(wy / 4)
- Math.floor(wy / 100)
+ Math.floor(wy / 400) - 32045;
//
// 2 - CALC WEEK NB
//
var d4:int = (((wJDN + 31741 - (wJDN % 7)) % 146097) % 36524) % 1461;
var L:int = Math.floor(d4 / 1460);
var d1:int = ((d4 - L) % 365) + L;
var wweekNb:int = Math.floor(d1 / 7) + 1;

return wweekNb;
}

public function nextWeek():void {
_date.date += 7;

dispatchEvent(new Event(DATE_CHANGED));
}

public function prevWeek():void {
_date.date -= 7;

dispatchEvent(new Event(DATE_CHANGED));
}

public function getDateFromWeekNr(week:uint, useSelectedYear:Boolean = false):Date {
var d:Date 	= new Date();
if (useSelectedYear) {
trace(_date.getFullYear());
d.setFullYear(_date.getFullYear());
trace(d.getFullYear());
}

var start:Number 		= 1 - (d.day);
d.date					+= start;				//start on monday
d.hours					= 0;
d.minutes				= 0;
d.seconds				= 0;
d.milliseconds			= 1;

var curWeek:int = calculateWeekNumber(d);

var diff:int 	= week - curWeek;
var retDate:Date = new Date();
if (useSelectedYear) {
retDate.setFullYear(_date.getFullYear());
}

var start:Number 		= 1 - (retDate.day);
retDate.date			+= start;				//start on monday
retDate.hours			= 0;
retDate.minutes			= 0;
retDate.seconds			= 0;
retDate.milliseconds	= 1;

retDate.date		+= (diff * 7);

return retDate;
}

public function hasWeek53():Boolean {
var date:Date = new Date();
date.month		= 11;
date.date		= 31;
var w:int = calculateWeekNumber(date);
if (w == 53) {
return true;
} else {
return false;
}
}

private function getIsoWeekNumber(dt:Date):Number { 
var week1:Date; 
var isoYear:Number = dt.fullYear; 

if (dt >= new Date(isoYear, 11, 29)) { 
week1 = getIsoWeekOne(isoYear + 1); 

if (compareDates(dt, week1) == -1) 
week1 = getIsoWeekOne(isoYear); 
else 
isoYear++; 
} else { 
week1 = getIsoWeekOne(isoYear); 
if (compareDates(dt, week1) == -1) 
week1 = getIsoWeekOne(--isoYear); 
} 
return Math.floor(((isoYear * 100) + datesDiff(dt, week1) / 7 + 1) % 100); 
} 
private function getIsoWeekOne(Year:Number):Date { 
var dt:Date = new Date(Year, 0, 4); 
var dayNumber:Number = dt.day; 
if (dayNumber == 0) dayNumber = 7; 
dt.date += 1 - dayNumber; 
return dt; 
} 
private function datesDiff(d1:Date, d2:Date):Number { 
return Math.floor(Math.abs((d1.time - d2.time) / 86400000)); 
} 
private function compareDates(d1:Date, d2:Date):Number { 
var date1Timestamp:Number = d1.getTime(); 
var date2Timestamp:Number = d2.getTime(); 

var result:Number = -1; 

if (date1Timestamp == date2Timestamp) 
result = 0; 
else if (date1Timestamp > date2Timestamp) 
result = 1; 

return result; 
} 
}
}

//--------------------------------------------------------------------------
//END OF PACKAGE
//Define the PrivateConstructorClass here so an instance cannot be by anyone
//except for the class defined in the above package
//--------------------------------------------------------------------------
class PrivateConstructorClass {
//--------------------------------------------------------------------------
//Constructor and Destructor
//--------------------------------------------------------------------------
public function PrivateConstructorClass() {
}
}
*/